home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 4.iso
/
public
/
bit
/
src
/
smooth.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-01
|
9KB
|
322 lines
/*
* $Id: smooth.c,v 0.91 1994/02/20 00:53:12 zhao Pre-Release $
*
*. This file is part of BIT shareware package. After the two weeks of
* free evaluation period, you are encouraged (required) to register
* your copy for a small registration fee, which is $35 for personal use
* and $50 for commercial, government and institutional use.
*
* Copyright(c) 1993, 1994 by T.C. Zhao.
* All rights reserved.
*
* Permission to use, copy, and distribute this software in its entirety
* for non-commercial purposes is hereby granted, provided that the
* above shareware and copyright notices and this permission notice
* appear in all copies and their documentation.
*
* This software may be modified for your own use, but modified versions
* may not be distributed without prior consent of the author.
*
* This software is provided "as is" without expressed or implied
* warranty of any kind.
*
*.
*
* Purpose:
* Smooth an image or a rectangular region of it using a special
* convolution kernel, either 3x3, 5x5 or 7x7.
*
*/
#if !defined(lint) && defined(F_ID)
char *id_smo = "$Id: smooth.c,v 0.91 1994/02/20 00:53:12 zhao Pre-Release $";
#endif
#include "bit.h"
#include "extern.h"
/************** Local variables ********************/
static Rect_t smoothreg, *sr; /* smoothing region */
static int rbcolor = 1; /* rubber band color */
static IPTR saved; /* input image */
static int morder; /* current smooth order */
static int **smooth_mat; /* smoothing matrix */
static int changed; /* raster status */
static int threshold[3]; /* threshold */
/**************** Local functions *************************/
static int smooth_init(IPTR, int);
static void set_smooth_mat(FL_OBJECT *, long);
static void create_form_smooth(void);
static FL_FORM *smooth;
static FL_OBJECT *tc[3]; /* threshold counter */
/****************************************************************
* Global entry point
****************************************************************/
int
img_smooth(IPTR im)
{
short val;
long dev;
create_form_smooth();
sr = &smoothreg;
smooth_init(im, 0);
install_wm_handler(smooth_init);
bit_show_form(smooth, FL_PLACE_HOTSPOT, 0, "Smooth");
do
{
dev = rubber_info(win_id, &val,
&sr->x, &sr->y, &sr->w, &sr->h, rbcolor, 15);
dev = bit_handle_event(dev, val);
}
while (dev != KEYBD || val != 27);
set_current_window(win_id);
rubber_finish();
bit_hide_form(smooth);
remove_wm_handler(smooth_init);
return 0;
}
/**********************************************************************
* Initialize rubber band location. Also handles window repositioning
* and window resizing
**********************************************************************/
static int
smooth_init(IPTR im, int wme)
{
static int oxi, oyi;
set_rubber_obj(RB_RECT);
set_rubber_bounds(1, im->xi, im->yi, im->w, im->h);
if (wme)
{
sr->x += im->xi - oxi;
sr->y += im->yi - oyi;
oxi = im->xi;
oyi = im->yi;
}
else
{
set_smooth_mat(0, 0);
sr->x = oxi = im->xi;
sr->y = oyi = im->yi;
sr->w = im->w;
sr->h = im->h;
}
return 0;
}
/** Select and make smoothing matrix **/
/* default smoothing matrix, a 3x3 and a 5x5 */
static short m_sm3x3[3][3] =
{
{5, 7, 5},
{7, 8, 7},
{5, 7, 5}
};
static short m_sm5x5[5][5] =
{
{5, 6, 7, 6, 5},
{6, 7, 8, 7, 6},
{7, 8, 8, 8, 7},
{6, 7, 8, 7, 6},
{5, 6, 7, 6, 5}
};
/* A lot of stronger than both 3x3 and 5x5 */
static short m_sm7x7[7][7] =
{
{6, 6, 6, 6, 6, 6, 6},
{6, 7, 7, 7, 7, 7, 6},
{6, 7, 8, 8, 8, 7, 6},
{6, 7, 8, 8, 8, 7, 6},
{6, 7, 8, 8, 8, 7, 6},
{6, 7, 7, 7, 7, 7, 6},
{6, 6, 6, 6, 6, 6, 6}
};
static void
set_smooth_mat(FL_OBJECT * ob, long q)
{
static int lastn = -1;
short *vec;
int i, j;
q = (ob == 0 ? 1 : fl_get_choice(ob));
morder = (q == 1 ? 3 : (q == 2 ? 5 : 7));
if (lastn != morder)
{
free_mat(smooth_mat);
smooth_mat = get_mat(morder, morder, sizeof(**smooth_mat));
for (i = 0; i < morder; i++)
{
vec = (morder == 3 ? m_sm3x3[i] :
(morder == 5 ? m_sm5x5[i] : m_sm7x7[i]));
for (j = 0; j < morder; j++)
smooth_mat[i][j] = *(vec + j);
}
lastn = morder;
}
}
/************************ undo *******************************/
/* ARGSUSED */
static void
undo_cb(FL_OBJECT * ob, long q)
{
if (changed)
{
free_image(imgptr);
imgptr = img_dup(saved);
imgptr->io->display(imgptr, -1, 0);
changed = 0;
}
}
/****** Save current change, and mark the undo point **********/
/* ARGSUSED */
static void
save_cb(FL_OBJECT * ob, long q)
{
if (changed)
{
free_image(saved);
saved = img_dup(imgptr);
changed = 0;
}
}
/***** call back routine to initiating smooth ****/
/* ARGSUSED */
static void
smooth_cb(FL_OBJECT * ob, long q)
{
if (!saved)
saved = img_dup(imgptr);
changed = (img_convolv(imgptr, smooth_mat, morder, morder,
threshold, sr, "Smoothing ...") >= 0);
}
/********************* Finish up ******************************/
/* ARGSUSED*/
static void
finish_smooth(FL_OBJECT * ob, long q)
{
fl_qenter(KEYBD, 27);
}
/*************** Solicit threshold input ***********************/
static void
threshold_cb(FL_OBJECT * ob, long q)
{
threshold[q] = fl_get_counter_value(ob);
if (IS_GRAY(imgptr))
{
fl_freeze_form(smooth);
threshold[0] = threshold[q];
if (q != 0)
fl_set_counter_value(tc[0], threshold[0]);
threshold[1] = threshold[q];
if (q != 1)
fl_set_counter_value(tc[1], threshold[1]);
threshold[2] = threshold[q];
if (q != 2)
fl_set_counter_value(tc[2], threshold[2]);
fl_unfreeze_form(smooth);
}
}
static void
create_form_smooth(void)
{
FL_OBJECT *obj;
static int fmade;
float dx, dy;
if (fmade)
return;
smooth = fl_bgn_form(FL_UP_BOX, 280.0, 250.0);
obj = fl_add_button(FL_HB, 0.0, 0.0, 280.0, 250.0, "");
fl_set_call_back(obj, help_cb, HELP_SMOOTH);
obj = fl_add_text(FL_NORMAL_TEXT, 30.0, 205.0, 220.0, 30.0, "Smooth");
fl_set_object_lcol(obj, 4);
fl_set_object_align(obj, FL_ALIGN_CENTER);
fl_set_object_lstyle(obj, FL_BOLD_STYLE);
fl_set_object_lsize(obj, 14.0);
obj = fl_add_choice(FL_NORMAL_CHOICE, 30.0, 140.0, 85.0, 25.0, "Order");
fl_set_object_boxtype(obj, FL_ROUNDED_BOX);
fl_set_object_lsize(obj, 10.0);
fl_set_object_align(obj, FL_ALIGN_TOP);
fl_set_object_lstyle(obj, FL_BOLD_STYLE);
fl_set_choice_fontsize(obj, 10.0);
fl_addto_choice(obj, "3x3");
fl_addto_choice(obj, "5x5");
fl_addto_choice(obj, "7x7");
fl_set_call_back(obj, set_smooth_mat, 0);
obj = fl_add_button(FL_NB, 30.0, 90.0, 85.0, 30.0, "Smooth");
fl_set_object_lsize(obj, 10.0);
fl_set_object_color(obj, FL_MAGIC1, FL_YELLOW);
fl_set_call_back(obj, smooth_cb, 0);
fl_set_form_hotspot(smooth, 30.0 + 40.0, 90.0 + 15.0);
/* the threshold */
tc[0] = obj = fl_add_counter(FL_NC, 135.0, 140.0, 125.0, 25.0, "Threshold");
fl_set_object_color(obj, 47, 1);
fl_set_object_lsize(obj, 10.0);
fl_set_object_align(obj, FL_ALIGN_TOP);
fl_set_counter_bounds(obj, 0.0, (float) PCMAXV);
fl_set_counter_precision(obj, 0);
fl_set_counter_step(obj, 1.0, 10.0);
fl_set_counter_value(obj, (float) threshold[0]);
fl_set_call_back(obj, threshold_cb, 0);
tc[1] = obj = fl_add_counter(FL_NC, 135.0, 115.0, 125.0, 25.0, "");
fl_set_object_color(obj, 47, 2);
fl_set_object_lsize(obj, 10.0);
fl_set_counter_bounds(obj, 0.0, (float) PCMAXV);
fl_set_counter_precision(obj, 0);
fl_set_counter_step(obj, 1.0, 10.0);
fl_set_counter_value(obj, (float) threshold[1]);
fl_set_call_back(obj, threshold_cb, 1);
tc[2] = obj = fl_add_counter(FL_NC, 135.0, 90.0, 125.0, 25.0, "");
fl_set_object_lsize(obj, 10.0);
fl_set_counter_bounds(obj, 0.0, (float) PCMAXV);
fl_set_counter_precision(obj, 0);
fl_set_counter_step(obj, 1.0, 10.0);
fl_set_counter_value(obj, (float) threshold[2]);
fl_set_call_back(obj, threshold_cb, 2);
dx = 75.0;
dy = 27;
obj = fl_add_button(FL_NB, 25.0, 15.0, dx, dy, "Save");
fl_set_object_lsize(obj, 10.0);
fl_set_call_back(obj, save_cb, 0);
obj = fl_add_button(FL_NB, 100.0, 15.0, dx, dy, "Undo");
fl_set_object_lsize(obj, 10.0);
fl_set_call_back(obj, undo_cb, 0);
obj = fl_add_button(FL_NB, 175.0, 15.0, dx, dy, "Done");
fl_set_object_lsize(obj, 10.0);
fl_set_call_back(obj, finish_smooth, 0);
fl_end_form();
fmade = 1;
}